/**
 * @addtogroup BAS
 * @{
 * @file
 * Iterator迭代器操作
 */
#include <assert.h>
#include <string.h>
#include "bas/bas_iterator.h"
#include "bas/bas_container.h"

static const char mcaId[] = "$Id$";

//取迭代器函数
#define _BAS_ITER_GET_FUNC(_tIterator, _pfnFunc)                           \
    (((T_Container *)(_tIterator).pvContainer)->ptCallBackTable->_pfnFunc) \

BAS_EXPORT void basIteratorGetValue(const T_Iterator tIterator, void *pvValue)
{
    assert(basIteratorIsValid(tIterator));
    assert(pvValue != NULL);

    T_IteratorGetValueFunction pfnGetValue = _BAS_ITER_GET_FUNC(tIterator, pfnGetValue);
    
    assert(pfnGetValue != NULL);

    pfnGetValue(tIterator, pvValue);
}

BAS_EXPORT void *basIteratorGetPointer(const T_Iterator tIterator)
{
    assert(basIteratorIsValid(tIterator));

    T_IteratorGetPointerFunction pfnGetPointer = _BAS_ITER_GET_FUNC(tIterator, pfnGetPointer);

    assert(pfnGetPointer != NULL);
    
    return pfnGetPointer(tIterator);
}

BAS_EXPORT void basIteratorSetValue(T_Iterator tIterator, const void *pvValue)
{
    assert(basIteratorIsValid(tIterator));
    assert(pvValue != NULL);

    T_IteratorSetValueFunction pfnSetValue = _BAS_ITER_GET_FUNC(tIterator, pfnSetValue);

    assert(pfnSetValue != NULL);
    
    pfnSetValue(tIterator, pvValue);
}

BAS_EXPORT T_Iterator basIteratorNext(const T_Iterator tIterator)
{
    assert(basIteratorIsValid(tIterator));

    T_IteratorNextFunction pfnNext = _BAS_ITER_GET_FUNC(tIterator, pfnNext);

    assert(pfnNext != NULL);

    return pfnNext(tIterator);
}

BAS_EXPORT T_Iterator basIteratorPrev(const T_Iterator tIterator)
{
    assert(basIteratorIsValid(tIterator));

    T_IteratorPrevFunction pfnPrev = _BAS_ITER_GET_FUNC(tIterator, pfnPrev);

    assert(pfnPrev != NULL);

    return pfnPrev(tIterator);
}

BAS_EXPORT bool basIteratorIsSameType(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    return tFirstIterator.eIteratorType == tSecondIterator.eIteratorType 
           && tFirstIterator.eContainerType == tSecondIterator.eContainerType;
}

BAS_EXPORT bool basIteratorIsValid(const T_Iterator tIterator)
{
    static const T_Iterator tEmptyIterator = {{0},0};
    T_IteratorIsValid pfnIsValid = NULL;

    if (memcmp(&tEmptyIterator, &tIterator, sizeof(T_Iterator)) == 0)
    {
        return false;
    }

    if (NULL == tIterator.pvContainer)
    {
        return false;
    }

    if ((pfnIsValid = _BAS_ITER_GET_FUNC(tIterator, pfnIsValid)) != NULL)
    {
        return pfnIsValid(tIterator);
    }
    else
    {
        return true;
    }
}

BAS_EXPORT bool basIteratorEqual(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    assert(basIteratorIsValid(tFirstIterator));
    assert(basIteratorIsValid(tSecondIterator));
    assert(basIteratorIsSameType(tFirstIterator, tSecondIterator));
    assert(tFirstIterator.pvContainer == tSecondIterator.pvContainer);

    T_IteratorEqualFunction pfnEqual = _BAS_ITER_GET_FUNC(tFirstIterator, pfnEqual);
    
    assert(pfnEqual != NULL);

    return pfnEqual(tFirstIterator, tSecondIterator);
}

BAS_EXPORT bool basIteratorLess(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    assert(basIteratorIsValid(tFirstIterator));
    assert(basIteratorIsValid(tSecondIterator));
    assert(basIteratorIsSameType(tFirstIterator, tSecondIterator));
    assert(tFirstIterator.pvContainer == tSecondIterator.pvContainer);

    T_IteratorLessFunction pfnLess = _BAS_ITER_GET_FUNC(tFirstIterator, pfnLess);

    assert(pfnLess != NULL);

    return pfnLess(tFirstIterator, tSecondIterator);
}

BAS_EXPORT bool basIteratorLessEqual(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    return basIteratorLess(tFirstIterator, tSecondIterator)
           || basIteratorEqual(tFirstIterator, tSecondIterator);
}

BAS_EXPORT bool basIteratorGreat(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    return !basIteratorLess(tFirstIterator, tSecondIterator)
           && !basIteratorEqual(tFirstIterator, tSecondIterator); 
}

BAS_EXPORT bool basIteratorGreatEqual(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    return !basIteratorLess(tFirstIterator, tSecondIterator);
}

BAS_EXPORT T_Iterator basIteratorNextN(const T_Iterator tIterator, const size_t nCount)
{
    assert(basIteratorIsValid(tIterator));

    T_IteratorNextNFunction pfnNextN = _BAS_ITER_GET_FUNC(tIterator, pfnNextN);

    assert(pfnNextN != NULL);

    return pfnNextN(tIterator, nCount);
}

BAS_EXPORT T_Iterator basIteratorPrevN(const T_Iterator tIterator, const size_t nCount)
{
    assert(basIteratorIsValid(tIterator));

    T_IteratorPrevNFunction pfnPrevN = _BAS_ITER_GET_FUNC(tIterator, pfnPrevN);

    assert(pfnPrevN != NULL);

    return pfnPrevN(tIterator, nCount);
}

BAS_EXPORT int basIteratorMinus(const T_Iterator tFirstIterator, const T_Iterator tSecondIterator)
{
    assert(basIteratorIsValid(tFirstIterator));
    assert(basIteratorIsValid(tSecondIterator));
    assert(basIteratorIsSameType(tFirstIterator, tSecondIterator));
    assert(tFirstIterator.pvContainer == tSecondIterator.pvContainer);

    T_IteratorMinusFunction pfnMinus = _BAS_ITER_GET_FUNC(tFirstIterator, pfnMinus);

    assert(pfnMinus != NULL);

    return pfnMinus(tFirstIterator, tSecondIterator);
}

/** @} */
